home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / comms / other / slrn / slrn_src / src / clientlib.c < prev    next >
C/C++ Source or Header  |  1999-05-14  |  22KB  |  1,026 lines

  1. /* -*- mode: C; mode: fold; -*- */
  2. /* This file is a MESS.  For that reason, I wrote sltcp.c which I regard as
  3.  * much cleaner.  I tried to clean this up but with at least 4 different
  4.  * TCP/IP implementations for VMS as well as TLI and BSD, there is not too
  5.  * much hope.  The routines in sltcp.c should be adequate for most Unix
  6.  * systems as well as OS/2.  Until VMS standardizes its TCP/IP interface
  7.  * the routines in this file will have to be used.
  8.  *
  9.  * Much of this file has been totally re-written.  Now all read/writes are
  10.  * to a file descriptor.  All reads take place via the function
  11.  * 'client_read' and all writes are done in 'client_write'.  These functions
  12.  * call the appropriate low level functions to perform the actual operation.
  13.  * Specifically, client_read calls:
  14.  *
  15.  *     socket_read (MULTINET)
  16.  *     do_netlib_read  (NETLIB)
  17.  *     read   (everything else)
  18.  *
  19.  * and client_write calls:
  20.  *
  21.  *     netlib_write (NETLIB)
  22.  *     socket_write (MULTINET)
  23.  *     write  (everything else)
  24.  *
  25.  * JED.
  26.  */
  27.  
  28. /*
  29.  * This software is Copyright 1991 by Stan Barber.
  30.  *
  31.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  32.  * use this software as long as: there is no monetary profit gained
  33.  * specifically from the use or reproduction or this software, it is not
  34.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  35.  * included prominently in any copy made.
  36.  *
  37.  * The author make no claims as to the fitness or correctness of this software
  38.  * for any use whatsoever, and it is provided as is. Any use of this software
  39.  * is at the user's own risk.
  40.  *
  41.  */
  42.  
  43. #if 0
  44. # define DEBUG_FILE "slrn.log"
  45. #endif
  46.  
  47. #include "config.h"
  48. #include "slrnfeat.h"
  49.  
  50. #include <stdio.h>
  51. #include <string.h>
  52. #include <signal.h>
  53. #include <errno.h>
  54.  
  55. #ifdef HAVE_UNISTD_H
  56. # include <unistd.h>
  57. #endif
  58.  
  59. #ifdef HAVE_STDLIB_H
  60. # include <stdlib.h>
  61. #endif
  62.  
  63. #include <sys/types.h>
  64.  
  65. #ifdef VMS
  66. /*{{{ VMS includes */
  67. # include "vms.h"
  68. # ifdef MULTINET
  69. #  include "multinet_root:[multinet.include.vms]inetiodef.h"
  70. #  include "multinet_root:[multinet.include.sys]types.h"
  71. # else
  72. #  if NETLIB
  73. #   include <descrip.h>
  74. #   include <types.h>
  75. #   include <iodef.h>
  76. #   include <stsdef.h>
  77. #   include "netlib_dir:netlibdef.h"
  78. #   define NNTP_PORT     119
  79. #   define INIT_SDESC(dsc, len, ptr) {(dsc).dsc$b_dtype = DSC$K_DTYPE_T;\
  80.      (dsc).dsc$b_class = DSC$K_CLASS_S; (dsc).dsc$w_length = (len);\
  81.      (dsc).dsc$a_pointer = (ptr);}
  82. #  else
  83. #   include <types.h>
  84. #   include <iodef.h>
  85. #   define    NNTP_PORT 119
  86. #  endif
  87. # endif
  88. /*}}}*/
  89. #endif
  90.  
  91. #include <ctype.h>
  92.  
  93. #ifdef TLI
  94. /*{{{ TLI includes */
  95. # include    <fcntl.h>
  96. # include    <tiuser.h>
  97. # include    <stropts.h>
  98. # include    <sys/socket.h>
  99. # define SLRN_LOADED_SYS_SOCKET_H
  100. # ifdef WIN_TCP
  101. #  include    <sys/in.h>
  102. # else
  103. #  include    <netinet/in.h>
  104. #  define SLRN_LOADED_NETINET_IN_H
  105. # endif
  106. # define    IPPORT_NNTP    ((unsigned short) 119)
  107. # include     <netdb.h>    /* All TLI implementations may not have this */
  108. /*}}}*/
  109. #else /* !TLI */
  110. # ifdef VMS
  111. /*{{{ More VMS includes */
  112. #  ifdef MULTINET
  113. #   include "multinet_root:[multinet.include]netdb.h"
  114. #   include "multinet_root:[multinet.include.sys]socket.h"
  115. #   include "multinet_root:[multinet.include.netinet]in.h"
  116. #   define SLRN_LOADED_NETINET_IN_H
  117. #   define SLRN_LOADED_SYS_SOCKET_H
  118. #  endif
  119. #  ifdef NETLIB
  120. #   include <descrip.h>
  121. #   include "netlib_dir:netlibdef.h"
  122. #  endif
  123. #  ifdef UCX
  124. #   include <netdb.h>
  125. #   include <socket.h>
  126. #   include <in.h>
  127. #   include <inet.h>
  128. #  endif
  129. /*}}}*/
  130. # else /* !VMS */
  131. #  include <sys/socket.h>
  132. #  include <netinet/in.h>
  133. #  define SLRN_LOADED_NETINET_IN_H
  134. #  define SLRN_LOADED_SYS_SOCKET_H
  135. #  ifndef EXCELAN
  136. #   include <netdb.h>
  137. #  endif /* !EXCELAN */
  138. # endif /* !VMS */
  139. #endif /* !TLI */
  140.  
  141. #ifdef HAVE_SYS_SOCKET_H
  142. # ifndef SLRN_LOADED_SYS_SOCKET_H
  143. #  include <sys/socket.h>
  144. #  define SLRN_LOADED_SYS_SOCKET_H
  145. # endif
  146. #endif
  147.  
  148. #ifdef HAVE_NETINET_IN_H
  149. # ifndef SLRN_LOADED_NETINET_IN_H
  150. #  include <netinet/in.h>
  151. #  define SLRN_LOADED_NETINET_IN_H
  152. # endif
  153. #endif
  154.  
  155. #ifdef HAVE_ARPA_INET_H
  156. # ifndef SLRN_LOADED_ARPA_INET_H
  157. #  include <arpa/inet.h>
  158. #  define SLRN_LOADED_ARPA_INET_H
  159. # endif
  160. #endif
  161.  
  162. #ifdef __unix__
  163. # ifdef MULTINET
  164. #  undef MULTINET
  165. # endif
  166. # ifdef NETLIB
  167. #  undef NETLIB
  168. # endif
  169. #endif
  170.  
  171. #ifdef EXCELAN
  172. /*{{{ EXCELAN defines */
  173. # define    NNTP_PORT    ((unsigned short) 119)
  174. # if __STDC__
  175. int connect(int, struct sockaddr *);
  176. unsigned short htons(unsigned short);
  177. unsigned long rhost(char **);
  178. int rresvport( int );
  179. int socket( int, struct sockproto *, struct sockaddr_in *, int );
  180. # endif
  181. /*}}}*/
  182. #endif
  183.  
  184. #ifdef DECNET
  185. # include <netdnet/dn.h>
  186. # include <netdnet/dnetdb.h>
  187. #endif /* DECNET */
  188.  
  189. #include "clientlib.h"
  190.  
  191. #include "server.h"
  192. #include "misc.h"
  193.  
  194. #ifndef NNTP_PORT
  195. # define NNTP_PORT 119
  196. #endif
  197.  
  198. #ifdef NEEDS_EXTERN_DECLARATIONS
  199. # define DECLARE_EXTERN(x) extern x;
  200. #else
  201. # define DECLARE_EXTERN(x)
  202. #endif
  203.  
  204. #ifdef NETLIB
  205. static void *Socket_Fd;
  206. #else
  207. static int Socket_Fd;
  208. #endif
  209.  
  210. #ifdef DEBUG_FILE
  211. static FILE *Debug_Fp;
  212. #endif
  213.  
  214. static int Server_Has_Been_Closed = 1;
  215.  
  216. static void client_close_server(void);
  217.  
  218. static int get_tcp_socket(char *, int);
  219. static void reset_read_buffer (void);
  220.  
  221. /*{{{ client_server_init_1 */
  222. /*
  223.  * client_server_init  Get a connection to the remote news server.
  224.  *
  225.  *    Parameters:    "machine" is the machine to connect to.
  226.  *
  227.  *    Returns:    -1 on error
  228.  *            server's initial response code on success.
  229.  *
  230.  *    Side effects:    Connects to server.
  231.  */
  232.  
  233. static int client_server_init_1 (char *machine, int port)
  234. {
  235.    int    sockt_rd;
  236. #ifdef DECNET
  237.    char    *cp;
  238.  
  239.    cp = slrn_strchr(machine, ':');
  240.  
  241.    if (cp && cp[1] == ':')
  242.      {
  243.     *cp = '\0';
  244.     sockt_rd = get_dnet_socket(machine);
  245.      }
  246.    else
  247.      sockt_rd = get_tcp_socket(machine, port);
  248. #else
  249.    sockt_rd = get_tcp_socket (machine, port);
  250. #endif
  251.  
  252.    if (sockt_rd < 0)
  253.      return (-1);
  254.  
  255. #ifndef NETLIB
  256.    Socket_Fd = sockt_rd;
  257. #endif
  258.  
  259.    /* Now get the server's signon message */
  260. #ifdef DEBUG_FILE
  261.    Debug_Fp = fopen (DEBUG_FILE, "w");
  262. #endif
  263.  
  264.    return 0;
  265. }
  266.  
  267. /*}}}*/
  268.  
  269. /*{{{ get_tcp_socket */
  270. /*
  271.  * get_tcp_socket -- get us a socket connected to the news server.
  272.  *
  273.  *    Parameters:    "machine" is the machine the server is running on.
  274.  *
  275.  *    Returns:    Socket connected to the news server if
  276.  *            all is ok, else -1 on error.
  277.  *
  278.  *    Side effects:    Connects to server.
  279.  *
  280.  *    Errors:        Printed via perror.
  281.  */
  282.  
  283. static int get_tcp_socket(char *machine, int nntpport)
  284. {
  285. #ifndef NETLIB
  286.    int    s = -1;
  287.    struct    sockaddr_in s_in;
  288. #endif
  289. #ifdef TLI
  290.    char     *t_alloc();
  291.    struct    t_call    *callptr;
  292.    /*
  293.     * Create a TCP transport endpoint.
  294.     */
  295.    if ((s = t_open("/dev/tcp", O_RDWR, (struct t_info*) 0)) < 0)
  296.      {
  297.     t_error("t_open: can't t_open /dev/tcp");
  298.     return(-1);
  299.      }
  300.    if(t_bind(s, (struct t_bind *)0, (struct t_bind *)0) < 0)
  301.      {
  302.     t_error("t_bind");
  303.     t_close(s);
  304.     return(-1);
  305.      }
  306.    memset ((char *) &s_in, 0, sizeof(s_in));
  307.    s_in.sin_family = AF_INET;
  308.  
  309.    if (nntpport < 0) nntpport = NNTP_PORT;
  310.    s_in.sin_port = htons((unsigned short) nntpport);
  311.  
  312.    if (!isdigit(*machine) ||
  313.        (long)(s_in.sin_addr.s_addr = inet_addr(machine)) == -1)
  314.      {
  315.     struct    hostent *gethostbyname(), *hp;
  316.     if((hp = gethostbyname(machine)) == NULL)
  317.       {
  318.          fprintf(stderr,"gethostbyname: %s: host unknown\n",
  319.              machine);
  320.          t_close(s);
  321.          return(-1);
  322.       }
  323.     memcpy ((char *) &s_in.sin_addr, hp->h_addr, hp->h_length);
  324.      }
  325.    /*
  326.     * Allocate a t_call structure and initialize it.
  327.     * Let t_alloc() initialize the addr structure of the t_call structure.
  328.     */
  329.    if ((callptr = (struct t_call *) t_alloc(s,T_CALL,T_ADDR)) == NULL)
  330.      {
  331.     t_error("t_alloc");
  332.     t_close(s);
  333.     return(-1);
  334.      }
  335.  
  336.    callptr->addr.maxlen = sizeof(s_in);
  337.    callptr->addr.len = sizeof(s_in);
  338.    callptr->addr.buf = (char *) &s_in;
  339.    callptr->opt.len = 0;            /* no options */
  340.    callptr->udata.len = 0;            /* no user data with connect */
  341.  
  342.    /*
  343.     * Connect to the server.
  344.     */
  345.    if (t_connect(s, callptr, (struct t_call *) 0) < 0)
  346.      {
  347.     t_error("t_connect");
  348.     t_close(s);
  349.     return(-1);
  350.      }
  351.  
  352.    /*
  353.     * Now replace the timod module with the tirdwr module so that
  354.     * standard read() and write() system calls can be used on the
  355.     * descriptor.
  356.     */
  357.  
  358.    if